package com.zeyu.framework.core.persistence;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.zeyu.framework.core.common.Constant;
import com.zeyu.framework.core.persistence.table.DatatablesCriterias;
import com.zeyu.framework.core.persistence.table.TableData;
import com.zeyu.framework.utils.CookieUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 分页类
 *
 * @param <T>
 */
public class Page<T> implements Serializable, Constant {

    // ================================================================
    // Constants
    // ================================================================

    /**
     * 页面大小，设置为“-1”表示不进行分页（分页无效）
     */
    private static final int DEFAULT_PAGE_SIZE = PAGE_DEFAULT_SIZE;

    // ================================================================
    // Fields
    // ================================================================

    // request data
    @JsonIgnore
    private DatatablesCriterias datatablesCriterias;

    //return data
    private TableData<T> tableData = null;

    // order by string, not used.
    @JsonIgnore
    private String orderBy;

    // ================================================================
    // Constructors
    // ================================================================

    /**
     * 构造方法
     */
    public Page() {
        this.datatablesCriterias = DatatablesCriterias.getNonCriterias();
        this.tableData = TableData.build(new ArrayList<>(), 0, this.datatablesCriterias);
    }

    /**
     * 构造方法
     *
     * @param request 传递 repage 参数，来记住页码
     */
    public Page(HttpServletRequest request) {
        this(request, DEFAULT_PAGE_SIZE);
    }

    /**
     * 构造方法
     *
     * @param request         传递 repage 参数，来记住页码
     * @param defaultPageSize 默认分页大小，如果传递 -1 则为不分页，返回所有数据
     */
    public Page(HttpServletRequest request, int defaultPageSize) {

        this.datatablesCriterias = DatatablesCriterias.getFromRequest(request);
        this.tableData = TableData.build(new ArrayList<>(), 0, this.datatablesCriterias);

        // 设置页码参数（传递repage参数，来记住页码）
        if (request.getParameter("repage") != null) {
            String no = CookieUtils.getCookie(request, "start");
            if (StringUtils.isNumeric(no)) {
                this.datatablesCriterias.setStart(Integer.parseInt(no));
            }
        }

        if (defaultPageSize == -1) {
            // 不分页
            this.datatablesCriterias.setLength(-1);
        }

        // 设置排序参数
        String orderBy = request.getParameter("orderBy");
        if (StringUtils.isNotBlank(orderBy)) {
            this.setOrderBy(orderBy);
        }
    }

    /**
     * 构造方法
     *
     * @param count 数据条数
     * @param list  本页数据对象列表
     */
    public Page(long count, List<T> list) {
        this.datatablesCriterias = DatatablesCriterias.getNonCriterias();
        this.tableData = TableData.build(list, count);
    }

    /**
     * 构造方法
     *
     * @param pageSize 条数
     */
    public Page(int pageSize) {
        this.datatablesCriterias = DatatablesCriterias.getNonCriterias();
        this.datatablesCriterias.setLength(pageSize);
        this.tableData = TableData.build(new ArrayList<>(), 0, this.datatablesCriterias);
    }

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    /**
     * 默认输出当前分页标签 <div class="page">${page}</div>
     */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    /**
     * 初始化参数
     */
    @JsonIgnore
    public void initialize() {

    }

    /**
     * 设置数据总数
     *
     * @param count 总数
     */
    @JsonIgnore
    public void setCount(long count) {
        this.tableData.setRecordsTotal(count);
    }

    /**
     * 设置本页数据对象列表
     *
     * @param list 数据对象列表
     */
    @JsonIgnore
    public Page<T> setList(List<T> list) {
        this.tableData.setData(list);
        return this;
    }

    /**
     * 获取本页数据对象列表
     *
     * @return List<T> 数据对象列表
     */
    @JsonIgnore
    public List<T> getList() {
        return this.tableData.getData();
    }

    /**
     * 获取查询排序字符串
     *
     * @return 排序字符串
     */
    @JsonIgnore
    public String getOrderBy() {
        if (this.orderBy == null) {
            return "";
        }
        // SQL过滤，防止注入
        String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|" + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
        Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
        if (sqlPattern.matcher(orderBy).find()) {
            return "";
        }
        return orderBy;
    }

    /**
     * 设置查询排序，标准查询有效， 实例： updatedate desc, name asc
     */
    @JsonIgnore
    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

    /**
     * 分页是否有效
     *
     * @return this.pageSize==-1
     */
    @JsonIgnore
    public boolean isDisabled() {
        return this.datatablesCriterias.getLength() == -1;
    }

    /**
     * 获取  FirstResult
     */
    @JsonIgnore
    public int getFirstResult() {
        int offset = this.datatablesCriterias.getStart();
        if (offset < 0) {
            offset = 0;
        }
        return offset;
    }

    /**
     * 获取  Page Number
     */
    @JsonIgnore
    public int getPageNum() {
        int offset = this.datatablesCriterias.getStart();
        if (offset <= 0) {
            return 1;
        }
        return offset / getMaxResults() + 1;
    }

    /**
     * 获取  MaxResults
     */
    @JsonIgnore
    public int getMaxResults() {
        int length = this.datatablesCriterias.getLength();
        if (length == -1) {
            // mybatis 分页组件, 0查询所有
            return 0;
        }
        return length > 0 ? length : DEFAULT_PAGE_SIZE;
    }

    // ================================================================
    // Getter & Setter
    // ================================================================

    /**
     * @return 请求参数信息
     */
    @JsonIgnore
    public DatatablesCriterias getDatatablesCriterias() {
        return datatablesCriterias;
    }

    /**
     * 设置请求参数信息
     */
    @JsonIgnore
    public void setDatatablesCriterias(DatatablesCriterias datatablesCriterias) {
        this.datatablesCriterias = datatablesCriterias;
    }

    /**
     * @return 应答结果信息
     */
    public TableData getTableData() {
        return tableData;
    }

    /**
     * 设置应答结果信息
     */
    public void setTableData(TableData<T> tableData) {
        this.tableData = tableData;
    }

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================
}
